#ifndef CutUtils_h
#define CutUtils_h

#include "AnalysisUtils.hxx"
#include "BaseDataClasses.hxx"
#include "AnaBoxB.hxx"

namespace cutUtils{

  /// Whether the closest TPC segment has > 18 nodes.
  bool TrackQualityCut(AnaTrackB& track);

  /// Whether the TPC segment has > 18 nodes.
  bool TPCTrackQualityCut(const AnaSubTrackB& tpcSeg);

  /// Whether the track starts in the specified fiducial volume. FGD, FGD1, FGD2
  /// and P0D fiducial volumes are supported, as well as TrECal and DsECal active 
  /// volumes. The detector volumes are defined in DetDef::fgd1min and similar 
  /// variables. The amount by which the detector volume is shrunk to form the 
  /// fiducial volume is specified by FVdefminFGD1 and similar variables.
  bool FiducialCut(const AnaTrackB& track, const SubDetId::SubDetEnum det = SubDetId::kFGD1);
  bool FiducialCut(const Float_t* pos, const SubDetId::SubDetEnum det = SubDetId::kFGD1);

  /// Get separation between two points
  float GetSeparationSquared(const Float_t* pos1, const Float_t* pos2);

  /// Utility function to assign arrays
  void AssignArray(Float_t* src, Float_t* dest, int n);
 
  /// Utility function to assign arrays
  void AssignArray(const Float_t* src, Float_t* dest, int n);

  /// Whether the track is muon-like, as defined for the NuMu analysis.
  bool MuonPIDCut(const AnaTrackB& track, bool prod5Cut = 0);

  /// Whether the track is muon-like, as defined for the anti-NuMu analysis.
  bool AntiMuonPIDCut(const AnaTrackB& track);

  /// Whether the track is muon-like, as defined for the numuBkgInAntiNuMode analysis.
  bool NumuBkgMuonPIDCut(const AnaTrackB& track);

  /// Whether the track is proton-like
  bool ProtonPIDCut(const AnaTrackB& track);

  /// The external veto cut, as defined for the NuMu analysis.
  AnaTrackB* FindVetoTrack(const AnaEventB& event, const AnaTrackB& track); // to save the veto track
  bool ExternalVetoCut(const AnaTrackB& cand, AnaTrackB* vetoTrack);
  bool ExternalVetoFGD2Cut(const AnaTrackB& cand, AnaTrackB* vetoTrack);

  /// Returns false if the track starts in the FGD1 FV, and has a start position
  /// that is more downstream than the end position.
  bool DeltaZCut(const AnaTrackB& track);

  /// Find the OOFV FGD track for a given detector and candidate track
  void FindOOFVtrack(const AnaEventB& event,  AnaBoxB& box,const AnaTrackB& mainTrack, const SubDetId::SubDetEnum det);

  /// Find the OOFV FGD track used by the FGD1 last layers cut
  void FindFGD1OOFVtrack(const AnaEventB& event, AnaBoxB& box);

  /// Find the OOFV FGD track used by the FGD2 last layers cut
  void FindFGD2OOFVtrack(const AnaEventB& event, AnaBoxB& box);

  /// Find the OOFV FGD track used by the FGD1 last layers cut (anti-NuMu analysis)
  void FindFGD1OOFVtrack_antinu(const AnaEventB& event, AnaBoxB& box);

  /// Find the OOFV FGD track used by the FGD2 last layers cut (anti-NuMu analysis)
  void FindFGD2OOFVtrack_antinu(const AnaEventB& event, AnaBoxB& box);

  /// Fill the analysis box. Only tracks with TPC information are
  /// considered. If qualityCut is true, then tracks must pass the
  /// TrackQualityCut function. Tracks must also start in the specified volume -
  /// FGD, FGD1, FGD2, and P0D are currently supported.
  ///
  /// The following members of the box are filled:
  /// * HMtrack............. The highest-momentum track.
  /// * HMNtrack............ The highest-momentum negative track.
  /// * HMPtrack............ The highest-momentum positive track.
  /// * NegativeTPCtracks... All the negative tracks, sorted by momentum.
  /// * PositiveTPCtracks... All the positive tracks, sorted by momentum.
  ///
  /// Again, only tracks with TPC information are considered.
  bool FindLeadingTracks(const AnaEventB& event, AnaBoxB& box, bool qualityCut = true, SubDetId::SubDetEnum det = SubDetId::kFGD, bool applyFiducialCut = true);

  /// Find Michel electrons (delayed time bins) in the FGD
  void FindFGDMichelElectrons(const AnaEventB& event, AnaBoxB& box);

  /// Retuns true if the two tracks start within the input tolerance 
  bool CommonVertexCut(const AnaTrackB& track1, const AnaTrackB& track2, int cutx, int cuty, int cutz);
}

#endif
